package com.thenie.chat.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.thenie.chat.pojo.User;
import com.thenie.chat.util.UUIDUtil;
import com.thenie.chat.util.WebSocketUtil;
import com.thenie.chat.vo.RandomChat;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketSession;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

import static com.thenie.chat.controller.DialogSocketHandler.SESSION_MAP;

/**
 * @author Thenie
 * @date 2022/7/24 17:32
 */
@Service
@Slf4j
public class RandomChatServiceImpl {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final BlockingQueue<RandomChat> REQUEST_QUEUE = new LinkedBlockingQueue<>(32);

    public static final String RANDOM_USER_PREFIX = "randomUser:";

    /**
     * 随机匹配聊天实现算法
     * 每20s统一匹配一次
     */
    @Scheduled(cron = "0/20 * * * * ?")
    public void randomChatMatch() {
        log.info("随机聊天匹配定时任务触发，当前任务数:{}", REQUEST_QUEUE.size());
        RandomChat q1 = null;
        try {
            while (REQUEST_QUEUE.size() > 0) {
                RandomChat q2 = REQUEST_QUEUE.take();
                //修改通过队列次数
                q2.setCount(q2.getCount() + 1);

                //判断当前请求是否在线
                if (SESSION_MAP.containsKey(String.valueOf(q2.getUser().getId()))) {
                    if (q1 == null) {
                        q1 = q2;
                    } else {

                        //获取socket连接
                        WebSocketSession socketSessionQ1 = SESSION_MAP.get(String.valueOf(q1.getUser().getId()));
                        WebSocketSession socketSessionQ2 = SESSION_MAP.get(String.valueOf(q2.getUser().getId()));

                        if (ObjectUtil.isEmpty(socketSessionQ1)) {
                            if (ObjectUtil.isEmpty(socketSessionQ2)) {
                                //q1和q2都离线，重新指向
                                q1 = null;
                            } else {
                                //q1离线，指向q2
                                q1 = q2;
                            }
                        } else if (ObjectUtil.isNotEmpty(socketSessionQ2) && !q1.getUser().getId().equals(q2.getUser().getId())) {
                            //q1 和 q2 都存在，可以匹配
                            //生成uid
                            String uuidQ1 = UUIDUtil.uuid();
                            String uuidQ2 = UUIDUtil.uuid();
                            //将信息保存到redis
                            redisTemplate.opsForValue().set(RANDOM_USER_PREFIX + uuidQ1, q1.getUser(), 10, TimeUnit.MINUTES);
                            redisTemplate.opsForValue().set(RANDOM_USER_PREFIX + uuidQ2, q2.getUser(), 10, TimeUnit.MINUTES);

                            //全部在线，进行发送
                            WebSocketUtil.sendRandomChatOkMsg(socketSessionQ1, uuidQ1 + "-" + uuidQ2);
                            WebSocketUtil.sendRandomChatOkMsg(socketSessionQ2, uuidQ2 + "-" + uuidQ1);

                            log.info("随机聊天匹配成功,username:{}与{}", q1.getUser().getUsername(), q2.getUser().getUsername());
                            q1 = null;
                        }
                    }
                }
            }

            //剩余一个用户没有匹配
            if (ObjectUtil.isNotEmpty(q1) && q1.getCount().intValue() < 2) {
                REQUEST_QUEUE.put(q1);
            }
        } catch (InterruptedException e) {

            e.printStackTrace();
        }
    }

    /**
     * 请求入队
     *
     * @param user
     * @throws InterruptedException
     */
    public void putRequestQueue(User user) throws InterruptedException {
        if (ObjectUtil.isNotEmpty(user)) {

            RandomChat rc = new RandomChat();
            rc.setUser(user);
            rc.setCount(0);

            REQUEST_QUEUE.put(rc);
        }
    }
}
